using System;
using Microsoft.SPOT;

// TODO: use Utility

namespace Unosquare.Labs.Utils
{
    static public class Extensions
    {
        public static byte[] ToByteArray(this uint vector)
        {
            var result = new byte[4];
            Microsoft.SPOT.Hardware.Utility.InsertValueIntoArray(result, 0, 4, vector);
            return new byte[] { result[3], result[2], result[1], result[0] };
        }

        public static byte[] ToByteArray(this ushort vector)
        {
            var result = new byte[2];
            Microsoft.SPOT.Hardware.Utility.InsertValueIntoArray(result, 0, 2, (uint)vector);
            return new byte[] { result[1], result[0] };
        }

        public static ushort ToUInt16(this byte[] value)
        {
            var reversedValue = new byte[2] { value[1], value[0] };
            return (ushort)Microsoft.SPOT.Hardware.Utility.ExtractValueFromArray(reversedValue, 0, 2);
        }

        public static char[] ToCharArray(this byte[] buffer, int offset = 0, int length = -1)
        {
            length = length == -1 ? buffer.Length - offset : length;
            char[] output = new char[length];
            var o = 0;
            for (var i = offset; i < offset + length; i++)
            {
                output[o] = (char)buffer[i];
                o++;
            }

            return output;
        }

        public static byte[] ToByteArray(this char[] chars, int offset = 0, int length = -1)
        {
            length = length == -1 ? chars.Length - offset : length;
            byte[] output = new byte[length];
            var o = 0;
            for (var i = offset; i < offset + length; i++)
            {
                output[o] = (byte)chars[i];
                o++;
            }

            return output;
        }

        public static byte[] Slice(this byte[] array, int offset, int length)
        {
            return Microsoft.SPOT.Hardware.Utility.ExtractRangeFromArray(array, offset, length);
        }

        public static char[] Slice(this char[] array, int offset, int length)
        {
            length = length == -1 ? array.Length - offset : length;
            char[] output = new char[length];
            var o = 0;
            for (var i = offset; i < length + offset; i++)
            {
                output[o] = array[i];
                o++;
            }

            return output;
        }

        public static byte[] ToByteArray(this string str)
        {
            return ToByteArray(str.ToCharArray());
        }

        public static string CreateString(this char[] chars)
        {
            return new string(chars);
        }

        public static string CreateString(this byte[] buffer)
        {
            return new string(buffer.ToCharArray());
        }

        public static byte[] AsByteArray(this byte source)
        {
            return new byte[] { source };
        }

        public static int IndexOf(this byte[] buffer, byte search)
        {
            for (int i = 0; i < buffer.Length; i++)
            {
                if (buffer[i] == search)
                    return i;
            }

            return -1;
        }

        public static int IndexOf(this char[] buffer, char search)
        {
            for (int i = 0; i < buffer.Length; i++)
            {
                if (buffer[i] == search)
                    return i;
            }

            return -1;
        }

        public static int IndexOf(this string str, char search)
        {
            var buffer = str.ToCharArray();
            for (int i = 0; i < buffer.Length; i++)
            {
                if (buffer[i] == search)
                    return i;
            }

            return -1;
        }

        public static void Ingest(this byte[] target, byte[] source, int targetIndex)
        {
            for (var i = 0; i < source.Length; i++)
            {
                target[i + targetIndex] = source[i];
            }
        }

        public static byte[] Append(this byte[] source, byte[] append)
        {
            return Microsoft.SPOT.Hardware.Utility.CombineArrays(source, append);
        }

        public static byte[] Prepend(this byte[] source, byte[] prepend)
        {
            return Microsoft.SPOT.Hardware.Utility.CombineArrays(prepend, source);
        }

        public static long TotalMilliseconds(this TimeSpan elapsed)
        {
            return (elapsed.Ticks / 10000);
        }
    }
}
